// ----------------------------------------------------------------------------
// hlsl_intrinsic.h
// ----------------------------------------------------------------------------
/*
 Description:
 HLSL intrinsic equivalents : HLSLと表記を似せた関数群. 
 Vectormathの組み込み関数のラッパ.
 
 ----------------------------------------------------------------
 使い方.
 
 各関数と、HLSL関数のリファレンスを参照してください. 
 
 */
#pragma once
#include <fw/base/core/macros.h>
#include <fw/base/math/vector3.h>
#include <fw/base/math/vector4.h>
#include <fw/base/math/matrix44.h>
#include <fw/base/math/matrix34.h>
#include <fw/base/math/matrix33.h>
#ifdef  FW_BASE_VECTORMATH_USE_SCALAR
#include <fw/base/math/_IMPL/hlsl_intrinsic.scalar.h>
#else
#include <fw/base/math/_IMPL/hlsl_intrinsic.sse.h>
#endif // FW_BASE_VECTORMATH_USE_SCALAR 

namespace fw
{
	FW_FORCE_INLINE vec3 abs(avec3 x)
	{
		return Vectormath::Aos::absPerElem(x);
	}

	FW_FORCE_INLINE vec4 abs(avec4 x)
	{
		return Vectormath::Aos::absPerElem(x);
	}
	
	FW_FORCE_INLINE vec3 acos(avec3 x)
	{
		return _impl_acos(x);
	}

	FW_FORCE_INLINE vec4 acos(avec4 x)
	{
		return _impl_acos(x);
	}

	FW_FORCE_INLINE vec3 asin(avec3 x)
	{
		return _impl_asin(x);
	}
	
	FW_FORCE_INLINE vec4 asin(avec4 x)
	{
		return _impl_asin(x);
	}

	FW_FORCE_INLINE vec3 atan(avec3 x)
	{
		return _impl_atan(x);
	}
	
	FW_FORCE_INLINE vec4 atan(avec4 x)
	{
		return _impl_atan(x);
	}

	FW_FORCE_INLINE vec3 ceil(avec3 x)
	{
		return _impl_ceil(x);
	}
	
	FW_FORCE_INLINE vec4 ceil(avec4 x)
	{
		return _impl_ceil(x);
	}

	FW_FORCE_INLINE vec3 clamp(avec3 x, avec3 min, avec3 max)
	{
		return Vectormath::Aos::minPerElem(Vectormath::Aos::maxPerElem(x, min), max);
	}
	
	FW_FORCE_INLINE vec4 clamp(avec4 x, avec4 min, avec4 max)
	{
		return Vectormath::Aos::minPerElem(Vectormath::Aos::maxPerElem(x, min), max);
	}

	FW_FORCE_INLINE vec3 cos(avec3 x)
	{
		return _impl_cos(x);
	}
	
	FW_FORCE_INLINE vec4 cos(avec4 x)
	{
		return _impl_cos(x);
	}
	
	FW_FORCE_INLINE vec3 cross(avec3 v0, avec3 v1)
	{
		return Vectormath::Aos::cross(v0, v1);
	}

	FW_FORCE_INLINE float distance(avec3 v0, avec3 v1)
	{
		return static_cast<float>(Vectormath::Aos::dist(Vectormath::Aos::Point3(v0), Vectormath::Aos::Point3(v1)));
	}
	
	FW_FORCE_INLINE float dot(avec3 v0, avec3 v1)
	{
		return static_cast<float>(Vectormath::Aos::dot(v0, v1));
	}
	
	FW_FORCE_INLINE float dot(avec4 v0, avec4 v1)
	{
		return static_cast<float>(Vectormath::Aos::dot(v0, v1));
	}

	FW_FORCE_INLINE vec3 floor(avec3 x)
	{
		return _impl_floor(x);
	}
	
	FW_FORCE_INLINE vec4 floor(avec4 x)
	{
		return _impl_floor(x);
	}

	FW_FORCE_INLINE vec3 frac(avec3 x)
	{
		return _impl_frac(x);
	}
	
	FW_FORCE_INLINE vec4 frac(avec4 x)
	{
		return _impl_frac(x);
	}
	
	FW_FORCE_INLINE const float length(avec3 x)
	{
		return static_cast<float>(Vectormath::Aos::length(x));
	}

	FW_FORCE_INLINE const float length(avec4 x)
	{
		return static_cast<float>(Vectormath::Aos::length(x));
	}

	FW_FORCE_INLINE const vec3 log2(avec3 x)
	{
		return _impl_log2(x);
	}
	
	FW_FORCE_INLINE const vec4 log2(avec4 x)
	{
		return _impl_log2(x);
	}

	FW_FORCE_INLINE const vec3 log10(avec3 x)
	{
		return _impl_log2(x);
	}
	
	FW_FORCE_INLINE const vec4 log10(avec4 x)
	{
		return _impl_log2(x);
	}
	
	FW_FORCE_INLINE const vec3 normalize(avec3 x)
	{
		return Vectormath::Aos::normalize(x);
	}
	
	FW_FORCE_INLINE const vec4 normalize(avec4 x)
	{
		return Vectormath::Aos::normalize(x);
	}

	FW_FORCE_INLINE const vec3 pow(avec3 x, avec3 y)
	{
		return _impl_pow(x, y);
	}
	
	FW_FORCE_INLINE const vec4 pow(avec4 x, avec4 y)
	{
		return _impl_pow(x, y);
	}
	
	FW_FORCE_INLINE const vec3 max(avec3 v0, avec3 v1)
	{
		return Vectormath::Aos::maxPerElem(v0, v1);
	}
	
	FW_FORCE_INLINE const vec4 max(avec4 v0, avec4 v1)
	{
		return Vectormath::Aos::maxPerElem(v0, v1);
	}

	FW_FORCE_INLINE const vec3 min(avec3 v0, avec3 v1)
	{
		return Vectormath::Aos::minPerElem(v0, v1);
	}
	
	FW_FORCE_INLINE const vec4 min(avec4 v0, avec4 v1)
	{
		return Vectormath::Aos::minPerElem(v0, v1);
	}

	FW_FORCE_INLINE vec3 lerp(avec3 v0, avec3 v1, float s)
	{
		return Vectormath::Aos::lerp(s, v0, v1);
	}
	
	FW_FORCE_INLINE vec4 lerp(avec4 v0, avec4 v1, float s)
	{
		return Vectormath::Aos::lerp(s, v0, v1);
	}

	FW_FORCE_INLINE vec3 reflect(avec3 i, avec3 n)
	{
		float r = 2.0f * fw::dot(i, n);
		return i - n * r;
	}

	FW_FORCE_INLINE vec3 reflact(avec3 i, avec3 n, float e)
	{
		float dp3 = fw::dot(i, n);
		float k = 1.0f - e * e * (1.0f - dp3 * dp3);
		return (k<0.0f) ? vec3(0,0,0) : e * i - (e * dp3 + sqrtf(k)) * n;
	}

	FW_FORCE_INLINE const vec3 sin(avec3 x)
	{
		return _impl_sin(x);
	}
	
	FW_FORCE_INLINE const vec4 sin(avec4 x)
	{
		return _impl_sin(x);
	}

	FW_FORCE_INLINE void sincos(avec3 x, vec3& s, vec3& c)
	{
		return _impl_sincos(x, s, c);
	}
	
	FW_FORCE_INLINE void sincos(avec4 x, vec4& s, vec4& c)
	{
		return _impl_sincos(x, s, c);
	}
	
	FW_FORCE_INLINE const vec3 sqrt(avec3 x)
	{
		return _impl_sqrt(x);
	}
	
	FW_FORCE_INLINE const vec4 sqrt(avec4 x)
	{
		return _impl_sqrt(x);
	}

	FW_FORCE_INLINE const vec3 rsqrt(avec3 x)
	{
		return _impl_sqrt(x);
	}
	
	FW_FORCE_INLINE const vec4 rsqrt(avec4 x)
	{
		return _impl_sqrt(x);
	}
	
} // namespace fw
